// XMLProfile.cpp
// By Emilio Guijarro Cameros
#include "stdafx.h"
#include "XMLProfile.h"

// CXMLProfile

CXMLProfile::CXMLProfile(LPCTSTR lpszProfileName) : pXMLDoc(NULL)
{		
	sFileName = _bstr_t(lpszProfileName);
}

CXMLProfile::~CXMLProfile()
{
}

// CXMLProfile member functions

bool CXMLProfile::writeProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue) 
{	
	IXMLDOMNodePtr nEntry;
	WCHAR szTemp[255];

	_itow(nValue, szTemp, 10);
	
	nEntry = blazeEntry(lpszSection, lpszEntry);
	nEntry->put_text(_bstr_t(szTemp));
	
	return true;
}

bool CXMLProfile::writeProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, 
									 LPCTSTR lpszData) 
{
	IXMLDOMNodePtr nEntry;

	nEntry = blazeEntry(lpszSection, lpszEntry);
	nEntry->put_text(_bstr_t(lpszData));
	
	return true;
}

int _httoi(const TCHAR *value)
{
  struct CHexMap
  {
    TCHAR chr;
    int value;
  };

  const int HexMapL = 16;
  CHexMap HexMap[HexMapL] =
  {
    {'0', 0}, {'1', 1},
    {'2', 2}, {'3', 3},
    {'4', 4}, {'5', 5},
    {'6', 6}, {'7', 7},
    {'8', 8}, {'9', 9},
    {'A', 10}, {'B', 11},
    {'C', 12}, {'D', 13},
    {'E', 14}, {'F', 15}
  };

  TCHAR *mstr = _tcsupr(_tcsdup(value));
  TCHAR *s = mstr;
  int result = 0;
  if (*s == '0' && *(s + 1) == 'X') s += 2;
  bool firsttime = true;
  while (*s != '\0')
  {
    bool found = false;
    for (int i = 0; i < HexMapL; i++)
    {
      if (*s == HexMap[i].chr)
      {
        if (!firsttime) result <<= 4;
        result |= HexMap[i].value;
        found = true;
        break;
      }
    }
    if (!found) break;
    s++;
    firsttime = false;
  }
  free(mstr);
  return result;
}

int CXMLProfile::getProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault) 
{
	IXMLDOMNodePtr nEntry;
	BSTR szContent = NULL;

	nEntry = blazeEntry(lpszSection, lpszEntry);
	nEntry->get_text(&szContent);
	
	if(szContent == NULL || _bstr_t(szContent) == _bstr_t(""))
	{
		IXMLDOMNodePtr nParent;
		
		nEntry->get_parentNode(&nParent);
		nParent->removeChild(nEntry);

		return nDefault;
	}	

	CString szPuli =szContent;
	szPuli.MakeLower();
	if(szPuli.Find("0x")==-1) {
	  return _wtoi(szContent);
	}

    return _httoi(szPuli);
}

LPSTR CXMLProfile::getProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCSTR lpszDefault, LPSTR lpBuffer, UINT nBufferSize)
{
	IXMLDOMNodePtr nEntry;
	BSTR szContent = NULL;

	nEntry = blazeEntry(lpszSection, lpszEntry);
	
	nEntry->get_text(&szContent);

	if(szContent == NULL || _bstr_t(szContent) == _bstr_t("")) {
		IXMLDOMNodePtr nParent;
		
		nEntry->get_parentNode(&nParent);
		nParent->removeChild(nEntry);

		strcpy(lpBuffer, lpszDefault);
		return (LPSTR)lpszDefault;
	}

	if(_bstr_t(szContent).length() < nBufferSize)
	{
		CHAR* szAsciiContent = _com_util::ConvertBSTRToString(szContent);

		strcpy(lpBuffer, szAsciiContent);
	}
	else
		throw CXMLProfileException("Buffer overflow");

	return lpBuffer;
}

IXMLDOMNodePtr CXMLProfile::blazeSection(LPCTSTR lpszSection)
{
	IXMLDOMElementPtr base, element;
	IXMLDOMNodePtr nSec, nResult;
	_bstr_t szName;
	BSTR bstrDomainDNSName;

	bool bSecFound = false, bEntryFound = false;

	pXMLDoc->get_documentElement(&base);
	
	for(base->get_firstChild(&nSec); nSec != NULL; nSec->get_nextSibling(&nSec)) {
		nSec->get_baseName(&bstrDomainDNSName);
        szName =bstrDomainDNSName;

		if(szName == _bstr_t(lpszSection)) {
			nResult = nSec;
			break;
		}
	}

	if(nSec == NULL) {
		element =pXMLDoc->createElement(_bstr_t(lpszSection));
		nResult =base->appendChild(element);
	}
	
	return nResult;
}

IXMLDOMNodePtr CXMLProfile::blazeEntry(LPCTSTR lpszSection, LPCTSTR lpszEntry)
{
	IXMLDOMElementPtr base, element;
	IXMLDOMNodePtr n1Sec, n1Entry;

	pXMLDoc->get_documentElement(&base);
	n1Sec =base->selectSingleNode(_bstr_t(lpszSection));

	if(n1Sec==NULL) {
		element =pXMLDoc->createElement(_bstr_t(lpszSection));
		n1Sec =base->appendChild(element);
	}

	n1Entry =n1Sec->selectSingleNode(_bstr_t(lpszEntry));

	if(n1Entry==NULL) {
	    element =pXMLDoc->createElement(_bstr_t(lpszEntry));
	    n1Entry =n1Sec->appendChild(element);
	}
	return n1Entry;
}

bool CXMLProfile::saveProfile()
{
	if(pXMLDoc != NULL && SUCCEEDED(pXMLDoc->save(_variant_t(sFileName))))
		return true;
	else
		return false;
}

bool CXMLProfile::loadProfile()
{
	if(pXMLDoc != NULL)
		return false;

	if(SUCCEEDED(pXMLDoc.CreateInstance(__uuidof(DOMDocument))))
	{
		if(FAILED(pXMLDoc->load(_variant_t(sFileName))))
			return false;
	}	

	IXMLDOMElementPtr base;
	
	pXMLDoc->get_documentElement(&base);

	if(base == NULL) {
		base =pXMLDoc->createElement(_bstr_t("profile"));
		pXMLDoc->appendChild(base);
	}

	return true;
}